/*	Pyramid.m - Pyramid model.
 *	Copyright (C) 1993 Corona Design, Inc. All rights reserved.
 *
 *	Abstract
 *		This model displays a tetrahedron with colored sides.
 *
 *	RCS path: 
 *		$Source: /Users/pkron/Projects/voxel/Pyramid/RCS/Pyramid.m,v $
 *	Modified: $Date: 93/09/15 12:35:12 $ by $Author: pkron $
 *	Current State: $State: Exp $ locked by $Locker:  $
 */

#import "Pyramid.h"

#import	<math.h>



#define	SQRT2	1.414214	
#define	SQRT3	1.732051
#define	SQRT6	(SQRT2*SQRT3)

@implementation Pyramid


	// unit tetrahedron with base on X,Y plane, vertex on Z-axis
static POINT	pyramid3D[4] = 
	{
		{ -.5,  SQRT3/6,       0, 1},
		{  .5,  SQRT3/6,       0, 1},
		{   0, -SQRT3/3,       0, 1},
		{   0,        0, SQRT6/3, 1}
	};

- drawFace: (int)point1 : (int)point2 : (int)point3
	{
	PSmoveto( pyramid[ point1][0], pyramid[ point1][1]);
	PSlineto( pyramid[ point2][0], pyramid[ point2][1]);
	PSlineto( pyramid[ point3][0], pyramid[ point3][1]);
	PSclosepath();
	PSfill();	
	return( self);
	}


- drawModel: (MATRIX)transform : (NXRect *)clip;
	{
	int		i;
	float	maxZ;
	BOOL	walked[4];
	int		drawOrder[4];
	NXRect	tmpRect;

								// map pyramid into view space		
	for ( i=0; i LT 4; ++i )
		{
		pyramid[i][0] = pyramid3D[i][0];
		pyramid[i][1] = pyramid3D[i][1];
		pyramid[i][2] = pyramid3D[i][2];
		pyramid[i][3] = pyramid3D[i][3];
		map( transform, &pyramid[i]);
		}
	
								// walk vertexes from closest to back	
	walked[0] = walked[1] = walked[2] = walked[3] = NO;
	for ( i=0; i LT 4; ++i)
		{
		int		max = 0;
		
		maxZ = 1E10;

		if ( !walked[0] )
			maxZ = pyramid[0][2];
			
		if ( !walked[1] && pyramid[1][2] LT maxZ )
			{
			max = 1;
			maxZ = pyramid[1][2];
			}

		if ( !walked[2] && pyramid[2][2] LT maxZ )
			{
			max = 2;
			maxZ = pyramid[2][2];
			}

		if ( !walked[3] && pyramid[3][2] LT maxZ )
			max = 3;
		
		walked[ max] = YES;
		drawOrder[i] = max;
		}

								// now project onto view plane
	for ( i=0; i LT 4; ++i )
		project( &pyramid[i]);
		
	for ( i=0; i LT 4; ++i )
		{
								// draw face opposite frontmost vertex		
		switch( drawOrder[i] )
			{
			case 0:
				PSsetrgbcolor( 1, 1, 0);	// yellow
				[self drawFace: 1 : 2 : 3];
				break;
				
			case 1:
				PSsetrgbcolor( 0, 0, 1);	// blue
				[self drawFace: 0 : 2 : 3];
				break;
				
			case 2:
				PSsetrgbcolor( 0, 1, 0);	// green
				[self drawFace: 0 : 1 : 3];
				break;
				
			case 3:
				PSsetrgbcolor( 1, 0, 0);	// red
				[self drawFace: 0 : 1 : 2];
				break;
			}
		}

								// compute new bounding rectangle
	NXSetRect( clip, pyramid[0][0] - .1, pyramid[0][1] - .1, .2, .2);
	NXSetRect( &tmpRect, pyramid[1][0] - .1, pyramid[1][1] - .1, .2, .2);
	NXUnionRect( &tmpRect, clip);	
	NXSetRect( &tmpRect, pyramid[2][0] - .1, pyramid[2][1] - .1, .2, .2);
	NXUnionRect( &tmpRect, clip);	
	NXSetRect( &tmpRect, pyramid[3][0] - .1, pyramid[3][1] - .1, .2, .2);
	NXUnionRect( &tmpRect, clip);	
	
	return( self);
	}


@end

#ifdef	_LOG
/*
 *	$Log:	Pyramid.m,v $
Revision 1.1  93/09/15  12:35:12  pkron
Created.

 */
#endif		
